#include "widget.h"
#include "ui_widget.h"
#include <QDebug>

#define WAVE_WIDTH  100
#define WAVE_HEIGHT_HELF 2047
#define Ang2Rad 0.01745

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    setWindowTitle("任意波形发生器");
    setFixedSize(860,590);

    //滑杆
    ui->label->setFixedSize(ui->label->width(),ui->label->height());
    ui->hsFrq->setMaximum(120);  //设置最大值
    ui->hsFrq->setMinimum(60);   //设置最小值
    ui->hsFrq->setValue(10); //设置初值
    ui->hsFrq->setTracking(false);  //不追踪
    spotnum=60;
    rbindex=1;
    connect(ui->hsFrq,&QSlider::valueChanged,this,&Widget::slot_showFrq);   //文本框显示计算出来的频率


    lineSeries=new QLineSeries(this); //实例化折线
    penSeries=QPen(Qt::green);  //画笔颜色
    lineSeries->setPen(penSeries);  //设置画笔

    chart=new XCustomChart(nullptr); //实例化图表对象
    chart->addSeries(lineSeries);   //讲折线系列添加到图表
    chart->setTheme(QtCharts::QChart::ChartThemeBlueCerulean);   //设置主题
    chart->legend()->hide();    //隐藏图例
    chart->setTitle("可以直接鼠标绘制改变波形");    //设置标题
    SelectWave(1);  //默认正弦波

    pChartView=new XChartView(chart,ui->widget);
    pChartView->setChart(chart);    //将图表绑定到视图
    pChartView->setRenderHint(QPainter::Antialiasing,true); //设置反走样
    QGridLayout* gridLayout =new QGridLayout(ui->widget);   //布局窗体
    gridLayout->addWidget(pChartView,0,0);
    ui->widget->setLayout(gridLayout);

    connect(lineSeries, &QLineSeries::hovered,this,&Widget::slot_serieHovered);    //高亮
    connect(lineSeries, &QLineSeries::pressed,chart,&XCustomChart::slot_clickOnPoint);    //绘制曲线

    //RadioButton改变波形
    connect(ui->rbSin,&QRadioButton::clicked,this,&Widget::slot_changeWave);
    connect(ui->rbCos,&QRadioButton::clicked,this,&Widget::slot_changeWave);
    connect(ui->rbSquare,&QRadioButton::clicked,this,&Widget::slot_changeWave);

    //扫描新增的串口
    portlist=new XSerialPortList(300);
    connect(portlist,&XSerialPortList::signal_onNewSerialPort,this,&Widget::slot_newPortList);
    portlist->ScanStart();

    serial=new QSerialPort(this);
    isOpened=false;
    connect(ui->pbOpen,&QPushButton::clicked,this,&Widget::slot_openSerial);
    connect(ui->pbGen,&QPushButton::clicked,this,&Widget::slot_sendWave);
}

Widget::~Widget()
{
    chart->removeAllSeries();   //析构图表
    if(serial->isOpen())    //关闭串口
    {
        serial->clear();
        serial->close();
    }
    delete ui;
}

void Widget::SelectWave(uint no)   //波形产生函数
{
    lineSeries->clear();
    switch(no)
    {
    case 1: //正弦波
        for(int i=0;i<(spotnum+1);i++)
        {
            lineSeries->append(i,WAVE_HEIGHT_HELF*qSin(i*(360.0/spotnum)*Ang2Rad)+WAVE_HEIGHT_HELF);
        }
        break;
    case 2: //余弦波
        for(int i=0;i<(spotnum+1);i++)
        {
            lineSeries->append(i,WAVE_HEIGHT_HELF*qCos(i*(360.0/spotnum)*Ang2Rad)+WAVE_HEIGHT_HELF);
        }
        break;
    case 3: //方波
        for(int i=0;i<spotnum/2;i++)
        {
            lineSeries->append(i,WAVE_HEIGHT_HELF*2);
        }
        for(int i=spotnum/2;i<(spotnum+1);i++)
        {
            lineSeries->append(i,0);
        }
        break;
    default:    //
        break;
    }
    chart->createDefaultAxes();     //添加默认坐标轴
    QValueAxis* axisX=new QValueAxis;
    axisX->setRange(0,spotnum);
    QValueAxis* axisY=new QValueAxis;
    axisY->setRange(0,4095);
    chart->setAxisX(axisX,lineSeries);
    chart->setAxisY(axisY,lineSeries);
}

void Widget::slot_serieHovered(const QPointF &, bool state)    //高亮曲线
{
    QPen penHighLight(Qt::white,5);
    if(state)
    {
        lineSeries->setPen(penHighLight);   //高亮曲线
    }
    else
    {
        lineSeries->setPen(penSeries);
    }
}

void Widget::slot_changeWave()  //更换波形
{
    QRadioButton* rb =dynamic_cast<QRadioButton*>(sender());
    QString rbName = rb->objectName();
    if(rbName=="rbSin")
    {
        SelectWave(1);
        rbindex=1;
    }
    else if(rbName=="rbCos")
    {
        SelectWave(2);
        rbindex=2;
    }
    else if(rbName=="rbSquare")
    {
        SelectWave(3);
        rbindex=3;
    }
}

void Widget::slot_newPortList(QStringList portName)    //串口列表
{
    ui->cbPort->clear();
    ui->cbPort->addItems(portName);
}

void Widget::slot_showFrq(int n) //文本框数值检测
{
    //本项目中更新一个波形数据需要45us
    int frq=1000000/(45*(n+1));
    ui->label->setText(QString("频率：%1Hz").arg(frq));
    spotnum=n;
    switch(rbindex)
    {
    case 1:
        SelectWave(1);
        break;
    case 2:
        SelectWave(2);
        break;
    case 3:
        SelectWave(3);
        break;
    default:
        break;
    }
}

void Widget::slot_openSerial() //打开串口
{
    if(serial!=NULL)
    {
        if(serial->isOpen())
        {
            serial->clear();
            serial->close();
        }
        //配置串口
        serial->setPortName(ui->cbPort->currentText());
        serial->setBaudRate(QSerialPort::Baud115200);
        serial->setDataBits(QSerialPort::Data8);
        serial->setParity(QSerialPort::NoParity);
        serial->setStopBits(QSerialPort::OneStop);
        serial->setFlowControl(QSerialPort::NoFlowControl);
        if(!serial->open(QIODevice::ReadWrite))
        {
            QMessageBox::information(NULL,"警告","无法打开串口",QMessageBox::Yes);
            return;
        }
        isOpened=true;
    }
}

QByteArray Widget::shortToByte(short i) //int转QByteArray
{
    QByteArray abyte0;
    abyte0.resize(2);
    abyte0[0] = (uchar) ((0xff00 & i) >> 8);
    abyte0[1] = (uchar) (0x00ff & i);
    return abyte0;
}


void Widget::Wave2Byte(const QLineSeries& ls,QByteArray& ba)    //波形变成字节数组
{
    const auto points=ls.points();
    auto itePoint = points.begin();
    for(;itePoint!=points.end();itePoint++)
    {
        ba.append(shortToByte((short)itePoint->y()));
    }
}

void Widget::slot_sendWave()   //发送波形
{

        if(isOpened)
        {
            waveArray.clear();
            ui->pbGen->setEnabled(false);

            Wave2Byte(*lineSeries,waveArray);

            serial->write(waveArray,waveArray.size()-1);
            ui->pbGen->setEnabled(true);
        }
        else
        {
            QMessageBox::information(NULL,"警告","串口未打开",QMessageBox::Yes);
        }
}
